﻿/* $RCSFile: AD.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/CRMWrapper3/Authentication/AD.cs $
 * $log$
 * Revision 19 2011/02/22 01:23:08  christian.surieux
 *   V4 Migration 22/2/11
 * Revision 19 2011/02/22 01:22:25  christian.surieux
 *   V4 Migration 22/2/11
 * Revision 6 2010/08/06 19:56:32  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Net;
using System.Web;
using System.Web.Services.Protocols;
using System.Web.Configuration;
using System.Security.Principal;

using AddonNice.Settings;
using AddonNice.Security;
using AddonNice.CRMWrapper;
using AddonNice.CRMWrapper.CRM4ADDisco;
using AddonNice.CRMWrapper.CRM4Server;

namespace AddonNice.CRMWrapper.Authentication
{
	public class AD : CrmAuthenticationBase
	{
		protected ICredentials _userCredentials             =   null;
		protected ICredentials _adminCredentials            =   null;
		protected Guid _runningUserId                       =   Guid.Empty;

		public override string UrlDisco
		{
			get
			{
				return string.Format("http://{0}:{1}/mscrmservices/2007/AD/CrmDiscoveryService.asmx",DiscoServerName,Port);
			}
		}

		public override CrmDiscoveryService CrmDisco
		{
			get
			{
				if (_CrmDisco == null)
				{
					_CrmDisco                       =   new CrmDiscoveryService();
					_CrmDisco.UseDefaultCredentials =   false;
					_CrmDisco.Credentials           =   adminCredentials;
					_CrmDisco.Url                   =   UrlDisco;
				}
				return _CrmDisco;
			}
		}

		/// <summary>
		/// Credentials used for the userService in AD mode
		/// If Addon Nice authentication mode is windows, it default to the windows user credential set in CredentialCache
		/// If Addon Nice authentication mode is forms, depends on:
		/// - if user authenticated, new credentials will be created from the current authenticated user, see AddonNiceIdentity
		/// - if not authenticated (anonymous), new credentials will be used from default crm user set in web.config
		/// </summary>
		public ICredentials userCredentials
		{
			get
			{
				if (_userCredentials == null)
				{
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( "[V]AD userCredentials GET BEG.",CRMTraceSwitch.Sw.Info);
					try
					{
						AuthenticationMode auth	            =	Config.AuthenticationMode;
						if ( CRMTraceSwitch.Sw.TraceVerbose )
							Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD userCredentials authenticationMode: {0}", auth),CRMTraceSwitch.Sw.Info);
						if ( auth == AuthenticationMode.Windows )
						{
							/*bool nulCred                    =   (System.Net.CredentialCache.DefaultNetworkCredentials == null);
							if ( CRMTraceSwitch.Sw.TraceVerbose )
								Trace.WriteLine( string.Format("[V]AD userCredentials Windows Mode, using CredentialCache Network Credential null: {0}.",nulCred),CRMTraceSwitch.Sw.Info);
							if ( !nulCred )
								 _userCredentials           =   System.Net.CredentialCache.DefaultNetworkCredentials;
							else */ _userCredentials           =   System.Net.CredentialCache.DefaultCredentials;
						}
						// Authentication == Forms
						else if (auth == AuthenticationMode.Forms)
						{
							if (HttpContext.Current.Request.IsAuthenticated 
								&& ( HttpContext.Current.User.Identity is AddonNiceIdentity ))// <- when in first setup we could have a FormIdentity
							{
								if ( CRMTraceSwitch.Sw.TraceVerbose )
									Trace.WriteLine( "[V]AD userCredentials Forms Mode, IsAuthenticated true.",CRMTraceSwitch.Sw.Info);
								AddonNiceIdentity AId   =   (AddonNiceIdentity)HttpContext.Current.User.Identity;
								_userCredentials        =   AId.Credentials;
							}
							else // If we are in Forms authentication with non authenticated user, we need some default account to logon
							{
								if ( CRMTraceSwitch.Sw.TraceVerbose )
									Trace.WriteLine(
									string.Format("[V]AD userCredentials Forms Mode not authenticated getting credentials from default values to allow logon: {0}-{1}-{2}.", Config.CRMDefaultAccount,
										CRMServiceDefaultAccount,CRMServiceDefaultPassword,CRMServiceDefaultDomain),CRMTraceSwitch.Sw.Info);
								// if not authenticated use default values
								_userCredentials        =   new NetworkCredential(CRMServiceDefaultAccount,CRMServiceDefaultPassword,CRMServiceDefaultDomain);
							}
						}
					}
					catch (Exception ex)
					{
						string msg  =   string.Format(CultureInfo.InvariantCulture,"[E]AD userCredentials ex: {0}", ex);
						if ( CRMTraceSwitch.Sw.TraceError )
							Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
						throw new CRMWrapperException(msg, ex);
					}
                    if (CRMTraceSwitch.Sw.TraceVerbose)
                        Trace.WriteLine("[V]AD userCredentials END.", CRMTraceSwitch.Sw.Info);
                }
				return _userCredentials;
			}
		 }

		/// <summary>
		/// Credentials for the CRM administrator specified in config file: new NetworkCredential 
		/// </summary>
		public ICredentials adminCredentials
		{
			get
			{
				if (_adminCredentials == null)
				{
					try
					{
						if ( CRMTraceSwitch.Sw.TraceVerbose )
							Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD adminCredentials Account : {0}, Pwd :{1}, Domain :{2}", CRMServiceAccount,CRMServicePassword,CRMServiceDomain),CRMTraceSwitch.Sw.Info);
						_adminCredentials   =   new NetworkCredential(CRMServiceAccount,CRMServicePassword,CRMServiceDomain);
					}
					catch (Exception ex)
					{
						string msg          =   string.Format(CultureInfo.InvariantCulture,"[E]AD adminCredentials ex: {0}", ex); 
						if ( CRMTraceSwitch.Sw.TraceError )
							Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
						throw new CRMWrapperException(msg, ex);
					}
				}

				return _adminCredentials;
			}
		}

		public override byte[] DownLoadFile(string url,ref bool OkDownload)
		{
			byte[] data                             =   null;
			OkDownload                              =   false;
			try
			{
				System.Net.WebClient myWebClient    =   new System.Net.WebClient();
				myWebClient.Credentials             =   adminCredentials;
				data                                =   myWebClient.DownloadData(url);
				OkDownload                          =   true;
			}
			catch (Exception ex)
			{
				if (CRMDynTraceSwitch.Sw.TraceError)
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AD DownLoadFile url '{0}', ex: {1}.", url, ex), CRMDynTraceSwitch.Sw.Info);
			}
			return data;
		}

		public override bool IsUserOk4Crm(string domain,string login,string pwd)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( "[V]AD IsUserOk4Crm BEG.",CRMTraceSwitch.Sw.Info);
			bool ret                            =   false;
			try
			{
				WhoAmIRequest request1		=   new WhoAmIRequest();
				NetworkCredential cred      =   new NetworkCredential(login,pwd,domain);
				Crm4WebService TestService	=	new Crm4WebService(ServiceUrl,false,cred,OrganizationName);
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD IsUserCredentialsOk Service Ok url: {0}",ServiceUrl),CRMTraceSwitch.Sw.Info);
				TestService.ExecuteRaw(request1);
				ret                         =   true;
			}
			catch (Exception ex)
			{
				string msg  =   string.Format("[E]AD IsUserOk4Crm ex: {0}.", ex);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
			}
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD IsUserOk4Crm END: {0}",ret),CRMTraceSwitch.Sw.Info);
			return ret;       
		}

		public override bool FindOrganization(string orgName)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD FindOrganization BEG orgName: {0}.",orgName),CRMTraceSwitch.Sw.Info);
			foreach (OrganizationDetail orgDetail in Organizations)
			{
				if ( orgDetail.OrganizationName.Equals(orgName) )
				{
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD FindOrganization found orgName: {0}, CrmServiceUrl: {1}, CrmMetadataServiceUrl: {2}.",
							orgName,orgDetail.CrmServiceUrl,orgDetail.CrmMetadataServiceUrl),CRMTraceSwitch.Sw.Info);
					Organization                                    =   orgDetail;
					OrganizationName                                =   orgDetail.OrganizationName;
					OrganizationFriendlyName                        =   orgDetail.FriendlyName;
					ServiceUrl                                      =   orgDetail.CrmServiceUrl;
					MetaDataServiceUrl                              =   orgDetail.CrmMetadataServiceUrl;
					WebApplicationUrl                               =   orgDetail.WebApplicationUrl;
					OrganizationId                                  =   orgDetail.OrganizationId;
					return true;
				}
			}
			return false;
		}
		
		/// <summary>
		/// Retrieve with disco service list of all org managed on this CRM server
		/// </summary>
		public override List<OrganizationDetail> Organizations
		{
			get
			{
				if ( (_Organizations == null) || (_Organizations.Count == 0 ))
				{
					try
					{
						_Organizations                              =   new List<OrganizationDetail>();
						RetrieveOrganizationsRequest orgRequest     =   new RetrieveOrganizationsRequest();
						RetrieveOrganizationsResponse orgResponse   =   (RetrieveOrganizationsResponse)CrmDisco.Execute(orgRequest);

						foreach (OrganizationDetail orgDetail in orgResponse.OrganizationDetails)
						{
							if ( CRMTraceSwitch.Sw.TraceVerbose )
								Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD Organizations GET found Organization: {0}",
									orgDetail.OrganizationName),CRMTraceSwitch.Sw.Info);
							_Organizations.Add(orgDetail);
						}
						if ( CRMTraceSwitch.Sw.TraceVerbose )
							Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD Organizations GET Count: {0}",_Organizations.Count),CRMTraceSwitch.Sw.Info);
					}
					catch (Exception ex)
					{
						string msg                                  =   string.Format("[E]AD Organizations GET ex: {0}", ex);
						if ( CRMTraceSwitch.Sw.TraceError )
							Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
						throw new CRMWrapperException(msg, ex);
					}
				}
				return _Organizations;
			}
		}

		/// <summary>
		/// Called by Ctor to create Admin crmservice objects necessary to first Crm calls with admin mode
		/// </summary>
		public override void InitAdminService(bool UsePreAuthenticate)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( "[V]AD InitAdminService BEG.",CRMTraceSwitch.Sw.Info);
			if (_adminAdminService == null)
			{
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD InitAdminService adminAdminService START OrganizationName: {0}.",OrganizationName),CRMTraceSwitch.Sw.Info);
				try
				{
					_adminAdminService		    =	new Crm4WebService(ServiceUrl,UsePreAuthenticate,adminCredentials,OrganizationName);
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD InitAdminService _adminAdminService Ok url: {0}",ServiceUrl),CRMTraceSwitch.Sw.Info);
				}
				catch (SoapException sx)
				{
					string msg  =   string.Format("[E]AD InitAdminService adminAdminService sx : {0}-{1}", sx, sx.Detail.InnerText);
					if ( CRMTraceSwitch.Sw.TraceError )
						Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException(msg, sx);
				}
				catch (CRMWrapperException)
				{
					throw;
				}
				catch (Exception ex)
				{
					string msg  =   string.Format("[E]AD InitAdminService adminAdminService ex: {0}", ex);
					if ( CRMTraceSwitch.Sw.TraceError )
						Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException(msg, ex);
				}
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( "[V]AD InitAdminService adminAdminService END ok",CRMTraceSwitch.Sw.Info);
			}
			if (_adminService == null)
			{
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( "[V]AD InitAdminService _adminService start",CRMTraceSwitch.Sw.Info);
				try
				{
// Pb Impersonate   _adminService			=	new Crm4WebService(_url,false,userCredentials,OrganizationName,(int)AuthenticationType,adminUserId);
					_adminService			=	adminAdminService;
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD InitAdminService _adminService.CallerIdValue : {0}", adminUserId),CRMTraceSwitch.Sw.Info);
				}
				catch (SoapException sx)
				{
					if ( CRMTraceSwitch.Sw.TraceError )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AD InitAdminService adminService sx : {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException("adminService soap: " + sx.Detail.InnerText, sx);
				}
				catch (CRMWrapperException)
				{
					throw;
				}
				catch (Exception ex)
				{
					if ( CRMTraceSwitch.Sw.TraceError )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AD InitAdminService adminService ex: {0}", ex),CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException("adminService ex", ex);
				}
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( "[V]AD InitAdminService _adminService end",CRMTraceSwitch.Sw.Info);
			}
			if ( _adminMetaService == null )
			{
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( "[V]AD InitAdminService _adminMetaService start",CRMTraceSwitch.Sw.Info);
				try
				{
					_adminMetaService			    =	new Crm4MetadataWebService(MetaDataServiceUrl,true,adminCredentials,OrganizationName);
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( "[V]AD InitAdminService _adminMetaService Ok",CRMTraceSwitch.Sw.Info);
				}
				catch (SoapException sx)
				{
					if ( CRMTraceSwitch.Sw.TraceError )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AD InitAdminService _adminMetaService sx : {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException("adminMetaService soap: " + sx.Detail.InnerText, sx);
				}
				catch (CRMWrapperException)
				{
					throw;
				}
				catch (Exception ex)
				{
					if ( CRMTraceSwitch.Sw.TraceError )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AD InitAdminService _adminMetaService ex: {0}", ex),CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException("adminMetaService ex", ex);
				}
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( "[V]AD InitAdminService _adminMetaService end",CRMTraceSwitch.Sw.Info);
			}
			// We need this to call wrapper only after Application_AuthenticateRequest has run
			// if Application_AuthenticateRequest is not runned we can get the Http.Context.Current.User and never reach this point
			 if ( CRMTraceSwitch.Sw.TraceVerbose )
				 Trace.WriteLine( "[V]AD InitAdminService END Ok",CRMTraceSwitch.Sw.Info);
		}
		
		/// <summary>
		/// Called by startWrapper to create different crmservice objects necessary to further running
		/// </summary>
		public override void InitServices(bool UsePreAuthenticate)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( "[V]AD InitServices BEG.",CRMTraceSwitch.Sw.Info);
			if (_userService == null)
			{
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( "[V]AD InitServices _userService START",CRMTraceSwitch.Sw.Info);
				try
				{
					//_userService	=	new Crm4WebService(ServiceUrl,UsePreAuthenticate,userCredentials,OrganizationName);
					_userService	=	new Crm4WebService(ServiceUrl,false,userCredentials,OrganizationName);
					if ( CRMTraceSwitch.Sw.TraceVerbose )
					{
						Trace.WriteLine(string.Format(CultureInfo.InvariantCulture,"[V]AD InitServices _userService Ok url: {0}, OrganizationName: {1}",ServiceUrl,OrganizationName),CRMTraceSwitch.Sw.Info);
						if ( _userCredentials is NetworkCredential )
							Trace.WriteLine(string.Format(CultureInfo.InvariantCulture,"[V]AD InitServices _userService Ok userCredentials: {0}, UserName: '{1}'",
								_userCredentials, ((NetworkCredential)_userCredentials).UserName),CRMTraceSwitch.Sw.Info);
						else
							Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "[V]AD InitServices _userService Ok userCredentials: {0}, unknown UserName",
								_userCredentials), CRMTraceSwitch.Sw.Info);
					}
				}
				catch (SoapException sx)
				{
					string msg      =   string.Format("[E]AD InitServices userService ex: {0}-{1}", sx, sx.Detail.InnerText);
					if ( CRMTraceSwitch.Sw.TraceError )
						Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException(msg, sx);
				}
				catch (CRMWrapperException)
				{
					throw;
				}
				catch (Exception ex)
				{
					string msg      =   string.Format("[E]AD InitServices userService ex: {0}", ex);
					if ( CRMTraceSwitch.Sw.TraceError )
						Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException(msg, ex);
				}
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( "[V]AD InitServices _userService END",CRMTraceSwitch.Sw.Info);
			}
			if (_userMetaService == null)
			{
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( "[V]AD InitServices _userMetaService start",CRMTraceSwitch.Sw.Info);
				try
				{
					_userMetaService    =	new Crm4MetadataWebService(MetaDataServiceUrl,UsePreAuthenticate,userCredentials,OrganizationName);
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD InitServices _userMetaService Ok url: {0}",MetaDataServiceUrl),CRMTraceSwitch.Sw.Info);
				}
				catch (SoapException sx)
				{
					if ( CRMTraceSwitch.Sw.TraceError )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AD InitServices _userMetaService sx : {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException("userMetaService soap: " + sx.Detail.InnerText, sx);
				}
				catch (CRMWrapperException)
				{
					throw;
				}
				catch (Exception ex)
				{
					if ( CRMTraceSwitch.Sw.TraceError )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AD InitServices _userMetaService ex: {0}", ex),CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException("userMetaService ex", ex);
				}
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( "[V]AD InitServices _userMetaService end",CRMTraceSwitch.Sw.Info);
			}
			try
			{
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( "[V]AD InitServices impersonate test start.",CRMTraceSwitch.Sw.Info);
				if ( impersonateUser )
				{
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( "[V]AD InitServices impersonate true.",CRMTraceSwitch.Sw.Info);
					((Crm4WebService)_userService).CrmAuthenticationTokenValue.CallerId =   userId;
				}
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD InitServices impersonateUser: {0}, userId: {1}, userName: {2}", impersonateUser, _userId, userName),CRMTraceSwitch.Sw.Info);
			}
			catch (SoapException sx)
			{
				string msg          =   string.Format("[E]AD InitServices ex: {0}-{1}", sx, sx.Detail.InnerText);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				string msg      =   string.Format("[E]AD InitServices ex: {0}", ex);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, ex);
			}

			// We need this to call wrapper only after Application_AuthenticateRequest has run
			// if Application_AuthenticateRequest is not runned we can get the Http.Context.Current.User and never reach this point
			 if ( CRMTraceSwitch.Sw.TraceVerbose )
				 Trace.WriteLine( "[V]AD InitServices END Ok",CRMTraceSwitch.Sw.Info);
		}

		protected bool _impersonateChecked                  =   false;
		public bool impersonateChecked     
		{
			get
			{
				return _impersonateChecked;
			}
		}

		protected Guid _dbUserId                            =   Guid.Empty;
		protected bool _impersonateUser                     =   false;
		/// <summary>
		/// When we  call this method from an iFrame, the identity may be different from logged user
		/// then we need to impersonate to logged user
		/// this property is the corresponding indicator 
		/// </summary>
		protected bool impersonateUser
		{
			get
			{
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD impersonateUser _impersonateChecked: {0}", _impersonateChecked),CRMTraceSwitch.Sw.Info);
				if (_impersonateChecked)
					return _impersonateUser;
				// retrieve a systemUser entity from context windows logon identity
				GetCurrentUser();
				// retrieve the userId from whoAmI API, calling it normally by the userService which uses CredentialCache in Windows authentication mode
				// this could be different in the case we are under an iFrame in CRM: it appeared that CRM iFrame are runned under NETWORK_SERVICE account
				try
				{
					GetUser();
				}
				catch ( Exception ex )
				{
					if ( CRMTraceSwitch.Sw.TraceError )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AD impersonateUser GetUser ex: {0}.", ex),CRMTraceSwitch.Sw.Info);
				}
				// if the logged user is not identical to user corresponding to the running identity process, we need to impersonate to have the real user calling the CRM
				// in this case the _dbUSer2 is the entity that need to act as the real user
				// so we do the swap
				if (_dbUserId  != Guid.Empty &&  _dbUserId != _userId)
				{
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD impersonateUser _dbUserId: {0} != _userId {1}", _dbUserId, _userId),CRMTraceSwitch.Sw.Info);
					_runningUserId              =   _userId;
					userId						=   _dbUserId;
					sysUser						=   _dbUser2;
					_impersonateUser            =   true;
				}
				_impersonateChecked             =   true;
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD impersonateUser : {0}", _impersonateUser),CRMTraceSwitch.Sw.Info);
				// Dispatch a SysUserSet event to all requesting objects
				CrmWrapperEventArgs ev          =   new CrmWrapperEventArgs(this,wrapperEventType.SysUserSet);
				Wrapper.OnCrmWrapperEvent(ev);
				return _impersonateUser;
			}
		}

		protected ADNDynSystemUser _dbUser2                     =   null; // crm user retrieved from current windows process identity (not current IIS authenticated user)
		/// <summary>
		/// Get the systemUser entity from the Context Identity by calling the CRM database systemusers with this key
		/// set it in _dbUser2 and _dbUserId 
		/// </summary>
		ADNDynSystemUser GetCurrentUser()
		{
			if (_dbUser2 != null)
				return _dbUser2;
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD GetCurrentUser BEG HttpContext.Current not null: {0}", HttpContext.Current!= null ),CRMTraceSwitch.Sw.Info);
			string CrmName				        =   string.Empty;
			Guid uId				            =	Guid.Empty; 
			// if request authenticated, try to get name from IIdentity
			// beware that Request.IsAuthenticated could be false and Request.LogonUserIdentity.IsAuthenticated true, 
			// because we are called from Windows_OnAuthenticate in global.asax
			IIdentity wid		                =   null;
			if ( SecurityTraceSwitch.Sw.TraceVerbose || AuthenticationTrace.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD GetCurrentUser Config.AuthenticationMode: {0}, Request.IsAuthenticated: {1}.", Config.AuthenticationMode,HttpContext.Current.Request.IsAuthenticated), 
					(SecurityTraceSwitch.Sw.TraceVerbose ) ? SecurityTraceSwitch.Sw.Info:AuthenticationTrace.Sw.Info);
			if (HttpContext.Current.Request.IsAuthenticated)
			{
				if (Config.AuthenticationMode == AuthenticationMode.Forms)
				{
					wid                         =   HttpContext.Current.User.Identity;
					CrmName                     =   wid.Name;
					if (CRMTraceSwitch.Sw.TraceVerbose)
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD GetCurrentUser CrmName set from HttpContext.Current.User.Identity: {0}, CrmName: {1}", HttpContext.Current.User.Identity, HttpContext.Current.User.Identity.Name), CRMTraceSwitch.Sw.Info);
					// we try to get a Crm userId from Identity, beware that it could be Guid.Empty
					if ( wid is AddonNiceIdentity )
					{
						AddonNiceIdentity Aid   =   (AddonNiceIdentity)wid;
						uId                     =   Aid.CrmImpersonateId;
						// real CRM name is not user name 
						CrmName                 =   string.Format("{0}\\{1}", Aid.CrmImpersonateDomain, Aid.CrmImpersonateLogin);
						if (CRMTraceSwitch.Sw.TraceVerbose)
							Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD GetCurrentUser get userId from IIdentity: {0}", uId), CRMTraceSwitch.Sw.Info);
					}
				}
				else if ( Config.AuthenticationMode == AuthenticationMode.Windows )
				{
					bool isADNPrinc             =   (HttpContext.Current.User is ADNCRMPrincipal);

					if (CRMTraceSwitch.Sw.TraceVerbose)
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD GetCurrentUser AuthenticationMode.Windows: Current.User is ADNCRMPrincipal: {0}.",isADNPrinc), CRMTraceSwitch.Sw.Info);
					// Update Identity with CRM ids for user
					if (isADNPrinc)
					{
						try
						{
							Guid wUserId            =   userId;
							if ( SecurityTraceSwitch.Sw.TraceVerbose || AuthenticationTrace.Sw.TraceVerbose )
								Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD GetCurrentUser setting AdonniceIdentity CrmId : {0}", wUserId),
												(SecurityTraceSwitch.Sw.TraceVerbose ) ? SecurityTraceSwitch.Sw.Info:AuthenticationTrace.Sw.Info);
							((ADNCRMPrincipal)HttpContext.Current.User).AddonNiceIdentity.SetCrmId(wUserId, (int)ADNTypeCodes.SystemUser);
						}
						catch (SoapException sx) // Not fatal here userId could not be retrieved -> pb HTTP 401
						{
							if ( CRMTraceSwitch.Sw.TraceError )
								Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AD GetCurrentUser SetCrmId ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
						}
						catch (Exception ex) // Not fatal here
						{
							if ( CRMTraceSwitch.Sw.TraceError )
								Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AD GetCurrentUser SetCrmId ex: {0}", ex),CRMTraceSwitch.Sw.Info);
						}
					}
					//CrmName                     =   HttpContext.Current.Request.LogonUserIdentity.Name; -> pb sous IIS7.5 NETWORK_SERVICES ????
					CrmName                     =   HttpContext.Current.User.Identity.Name;
					if (CRMTraceSwitch.Sw.TraceVerbose)
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD GetCurrentUser CrmName set from LogonUserIdentity.Name: {0}", CrmName), CRMTraceSwitch.Sw.Info);
				}
			}
			// if we get a valid Id, get user from this Id
			if ( uId != Guid.Empty )
			{
				_dbUser2				        =   GetUserById2(uId);
				if ( _dbUser2 != null )
				{
					_dbUserId		            =   _dbUser2.systemuserid;
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD GetCurrentUser END Ok from userId: {0}, CrmName: {1}", uId,_dbUser2.domainname),CRMTraceSwitch.Sw.Info);
					return _dbUser2;
				}
			}
			// if CrmName still empty, take the default account
			if ( (Config.AuthenticationMode == AuthenticationMode.Forms) && string.IsNullOrEmpty(CrmName) )
			{
				CrmName                         =   string.Format("{0}\\{1}",CRMServiceDefaultDomain,CRMServiceDefaultAccount);
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD GetCurrentUser taking default identity to retrieve user CrmName: {0}", CrmName),CRMTraceSwitch.Sw.Info);
			}
			if ( !string.IsNullOrEmpty(CrmName) )
			{
				_dbUser2                        =   GetUserByDomainName2(CrmName);
				if (_dbUser2 != null)
				{
					_dbUserId                   =   _dbUser2.systemuserid;
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AD GetCurrentUser END Ok with domainName: dbUser2.domainname: {0}, CrmName : {1}, dbUserId: {2}", 
							new object[] { _dbUser2.domainname, CrmName, _dbUserId }),CRMTraceSwitch.Sw.Info);
					return _dbUser2;
				}
			}
			const string msgex                  =   "[E]AD GetCurrentUser null.";
			if ( CRMTraceSwitch.Sw.TraceError )
				Trace.WriteLine( msgex,CRMTraceSwitch.Sw.Info);
			return null;
			// we should have a user here so don't allow to continue
			//throw new CRMWrapperException(msgex);
		}

		public AD(CrmWrapper4 wrp) : base(wrp)
		{
			 if ( CRMTraceSwitch.Sw.TraceVerbose )
				 Trace.WriteLine( "[V]AD Ctor Called",CRMTraceSwitch.Sw.Info);
		}
}
}
